home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
cool
/
cool.lha
/
lice
/
mkdepend
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-04
|
14KB
|
689 lines
/*
//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
* $XConsortium: main.c,v 1.33 89/07/21 11:35:21 jim Exp $
*/
#include "def.h"
#ifdef hpux
#define sigvec sigvector
#endif /* hpux */
#include <signal.h>
#include <errno.h>
#ifdef VMS
#include <unixio.h>
#endif
#ifdef DEBUG
int debug;
#endif
/**
** MODIFIED: 06/25/90 by MBN
**
** Added the -X option to generate dependencies for a file but *not* an RCS
** dependency. This is useful for LEX and YACC generated files that have
** include statements, but whose source is machine-produced.
**/
/**
** MODIFIED: 06/13/90 by MBN
**
** Modified basename() function to check extensions and added SourceExtensions
** array of valid source filename extensions.
**/
/**
** MODIFIED: 06/08/90 by MBN
**
** Add a dependency to automatically link each header file when checkout
** out to the project include directory if the command line option -L
** is specified
**/
/**
** MODIFIED: 05/16/90 by MBN
**
** Add a dependency for each file in the file list on the command line to
** its RCS master of the form "foo.h :: $(RCSDIR)foo.h$(RCSEXT)" if the
** command line option -R (for RCS) is specified
**/
/**
** MODIFIED: 05/14/90 by MBN
**
** If the extension on a file is .l, .y, .h, .c, or .C don't zap it! This
** allows mkdepend to calculate dependencies for files contained in the SRCS
** list in the Imake file. If this is not done, then "foo.h" becomes "foo.o"
**/
/**
** MODIFIED: 05/11/90 by MBN
**
** Removed hard-coded path separator character and changed to a user-defined
** character constant. The symbol PATHSEP defaults to '/' but can be over
** ridden on the command line to mkdepend.
**/
char path_sep = PATHSEP;
/* The following is used to find the end of the directory information. In
UNIX, it is '/'; in VMS, however, it is ']', which differs from the path
separator '.'.
*/
char path_end = PATHSEP;
char *ProgramName;
char *directives[] = {
"if",
"ifdef",
"ifndef",
"else",
"endif",
"define",
"undef",
"include",
"line",
"pragma",
"error",
"ident",
"sccs",
"elif",
"eject",
NULL
};
/**
** SourceExtensions contains the extensions for files that have conversion
** rules, that is, get transposed from one type of "thing" to another. Any
** file passed on the command line that does *NOT* have one of these extensions
** is assumed to be a miscellaneous file and, if the -R (RCS Checkout) flag
** is provided, will result in a dependency added for to check out the file
** from under RCS control.
**/
char *SourceExtensions[] = {
"h",
"hxx",
"c",
"cxx",
"C",
"y",
"Y",
"l",
"L",
NULL
};
struct symtab predefs[] = {
#ifdef apollo
{"apollo", NULL},
#endif
#ifdef ibm032
{"ibm032", NULL},
#endif
#ifdef sun
{"sun", NULL},
#endif
#ifdef os2
{"os2", NULL},
#endif
#ifdef DOS
{"DOS", NULL},
#endif
#ifdef hpux
{"hpux", NULL},
#endif
#ifdef vax
{"vax", NULL},
#endif
#ifdef VMS
{"VMS", NULL},
#endif
#ifdef cray
{"cray", NULL},
#endif
#ifdef CRAY
{"CRAY", NULL},
#endif
#ifdef att
{"att", NULL},
#endif
#ifdef mips
{"mips", NULL},
#endif
#ifdef ultrix
{"ultrix", NULL},
#endif
#ifdef mc68000
{"mc68000", NULL},
#endif
#ifdef mc68020
{"mc68020", NULL},
#endif
#ifdef __GNUC__
{"__GNUC__", NULL},
#endif
#ifdef __STDC__
{"__STDC__", NULL},
#endif
{NULL, NULL}
};
struct symtab deflist[ MAXDEFINES ];
struct inclist inclist[ MAXFILES ],
*inclistp = inclist;
char *filelist[ MAXFILES ];
char *dependonlylist[ MAXFILES ];
char *includedirs[ MAXDIRS ];
char *notdotdot[ MAXDIRS ];
char *objfile = ".o";
char *startat = "# DO NOT DELETE THIS LINE -- mkdepend depends on it.";
int width = 78;
boolean printed = FALSE;
boolean verbose = FALSE;
boolean show_where_not = FALSE;
boolean rcs_dependency = FALSE;
boolean link_dependency = FALSE;
void redirect();
static
#ifdef SIGNALRETURNSINT
int
#else
void
#endif
catch (sig)
int sig;
{
fflush (stdout);
log_fatal ("got signal %d\n", sig);
}
#ifndef os2
#ifndef USG
struct sigvec sig_vec = {
catch,
(1<<(SIGINT -1))
|(1<<(SIGQUIT-1))
|(1<<(SIGBUS-1))
|(1<<(SIGILL-1))
|(1<<(SIGSEGV-1))
|(1<<(SIGHUP-1))
|(1<<(SIGPIPE-1))
|(1<<(SIGSYS-1)),
0
};
#endif /* USG */
#endif /* os2 */
main(argc, argv)
int argc;
char **argv;
{
register struct symtab *symp = deflist;
register char **fp = filelist;
register char **incp = includedirs;
register char **temp;
register char **dp = dependonlylist;
register char *p;
register struct inclist *ip;
char *makefile = NULL;
struct filepointer *filecontent;
struct symtab *psymp = predefs;
char *endmarker = NULL;
char buf[ 2 ];
ProgramName = argv[0];
while (psymp->s_name)
*symp++ = *psymp++;
for(argc--, argv++; argc; argc--, argv++) {
/* if looking for endmarker then check before parsing */
if (endmarker && strcmp (endmarker, *argv) == 0) {
endmarker = NULL;
continue;
}
if (**argv != '-') {
/* scan existing filenames and only add to list if
this new one has not already been specified */
for (temp = filelist; *temp; temp++)
if(strcmp(argv[0],*temp) == 0)
break;
if (*temp == NULL)
*fp++ = argv[0];
continue;
}
switch(argv[0][1]) {
case '-':
endmarker = &argv[0][2];
if (endmarker[0] == '\0') endmarker = "--";
break;
case 'D':
symp->s_name = argv[0]+2;
if (*symp->s_name == '\0') {
symp->s_name = *(++argv);
argc--;
}
for (p=symp->s_name; *p ; p++)
if (*p == '=') {
*p++ = '\0';
break;
}
symp->s_value = p;
symp++;
break;
case 'R':
rcs_dependency = TRUE;
break;
case 'L':
link_dependency = TRUE;
break;
case 'X':
if(argv[0][2] != ' ' && argv[0][2] != '\0')
{
*dp++ = &(argv[0][2]);
*fp++ = &(argv[0][2]);
}
break;
case 'I':
*incp++ = argv[0]+2;
if (**(incp-1) == '\0') {
*(incp-1) = *(++argv);
argc--;
}
break;
/* do not use if endmarker processing */
case 'w':
if (endmarker) break;
if (argv[0][2] == '\0') {
argv++;
argc--;
width = atoi(argv[0]);
} else
width = atoi(argv[0]+2);
break;
case 'o':
if (endmarker) break;
if (argv[0][2] == '\0') {
argv++;
argc--;
objfile = argv[0];
} else
objfile = argv[0]+2;
break;
case 'v':
if (endmarker) break;
verbose = TRUE;
#ifdef DEBUG
if (argv[0][2])
debug = atoi(argv[0]+2);
#endif
break;
case 's':
if (endmarker) break;
startat = argv[0]+2;
if (*startat == '\0') {
startat = *(++argv);
argc--;
}
if (*startat != '#')
log_fatal("-s flag's value should start %s\n",
"with '#'.");
break;
case 'f':
if (endmarker) break;
makefile = argv[0]+2;
if (*makefile == '\0') {
makefile = *(++argv);
argc--;
}
break;
case 'P': /* User-specified path separator character */
if( argv[0][2] == '\0' || argv[0][2] == ' ')
log_fatal("invalid pathname separator specified\n");
path_sep = argv[0][2];
break;
case 'Q': /* User-specified path end character */
path_end = argv[0][2];
break;
/* Ignore -O, -g so we can just pass ${CFLAGS} to
makedepend
*/
case 'O':
case 'g':
break;
default:
if (endmarker) break;
/* log_fatal("unknown opt = %s\n", argv[0]); */
do_log("ignoring option %s\n", argv[0]);
}
}
redirect(startat, makefile);
/*
* catch signals.
*/
#ifdef USG
/* should really reset SIGINT to SIG_IGN if it was. */
signal (SIGHUP, catch);
signal (SIGINT, catch);
signal (SIGQUIT, catch);
signal (SIGILL, catch);
signal (SIGBUS, catch);
signal (SIGSEGV, catch);
signal (SIGSYS, catch);
#else
#ifndef os2
sigvec(SIGHUP, &sig_vec, (struct sigvec *)0);
sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
#endif
#endif
/*
* now peruse through the list of files.
*/
for(fp=filelist; *fp; fp++) {
if(is_source_file(*fp)) {
filecontent = getfile(*fp);
ip = newinclude(*fp, (char *)NULL);
find_includes(filecontent, ip, ip, 0);
freefile(filecontent);
recursive_pr_include(ip, ip->i_file, *fp);
}
if(is_depend_only_file(*fp) == TRUE) {
sprintf(buf, "\n");
fwrite(buf, strlen(buf), 1, stdout);
}
else if(rcs_dependency == TRUE) {
rcs_pr(*fp, "$(RCSDIR)", "$(RCSEXT)");
if (link_dependency == TRUE)
link_pr(*fp);
}
inc_clean();
}
if (printed)
printf("\n");
exit(0);
}
int is_source_file(file)
register char *file;
{
register char *p, **q;
for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
if (*p == path_sep)
p++;
file = copy(p);
for(p=file+strlen(file); p>file && *p != '.'; p--) ;
if (*p == '.')
{
for( q = SourceExtensions; *q; q++)
if( !strcmp(*q, (p+1)) )
{
return 1;
}
}
return 0;
}
int is_depend_only_file(file)
register char *file;
{
register char *p, **q;
for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
if (*p == path_sep)
p++;
for( q = dependonlylist; *q; q++)
if( !strcmp(*q, p) )
return 1;
return 0;
}
struct filepointer *getfile(file)
char *file;
{
register int i;
struct filepointer *content;
struct stat st;
FILE *fd;
content = (struct filepointer *)malloc(sizeof(struct filepointer));
if ((fd = fopen(file, "r")) == NULL) {
do_log("cannot open \"%s\" [errno=%d]\n", file, errno);
content->f_p = content->f_base = content->f_end = malloc(1);
*content->f_p = '\0';
return(content);
}
stat(file, &st);
content->f_len = st.st_size+1;
content->f_base = malloc(content->f_len);
if (content->f_base == NULL)
log_fatal("cannot allocate mem\n");
for (i = 0; i < st.st_size; ++i)
content->f_base[i] = getc (fd);
fclose(fd);
content->f_p = content->f_base;
content->f_end = content->f_base + st.st_size;
*content->f_end = '\0';
content->f_line = 0;
return(content);
}
freefile(fp)
struct filepointer *fp;
{
free(fp->f_base);
free(fp);
}
/*VARARGS*/
log_fatal(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
char* x0;
{
do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
exit (1);
}
/*VARARGS0*/
do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
char* x0;
{
fprintf(stderr, "%s: ", ProgramName);
fprintf(stderr, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
}
char *copy(str)
register char *str;
{
register char *p = malloc(strlen(str) + 1);
strcpy(p, str);
return(p);
}
match(str, list)
register char *str, **list;
{
register int i;
for (i=0; *list; i++, list++)
if (strcmp(str, *list) == 0)
return(i);
return(-1);
}
/*
* Get the next line. We only return lines beginning with '#' since that
* is all this program is ever interested in.
*/
char *getline(filep)
register struct filepointer *filep;
{
register char *p, /* walking pointer */
*eof, /* end of file pointer */
*bol; /* beginning of line pointer */
register lineno; /* line number */
p = filep->f_p;
eof = filep->f_end;
if (p >= eof)
return((char *)NULL);
lineno = filep->f_line;
for(bol = p--; ++p < eof; ) {
if (*p == '/' && *(p+1) == '*') { /* consume comments */
*p++ = ' ', *p++ = ' ';
while (*p) {
if (*p == '*' && *(p+1) == '/') {
*p++ = ' ', *p = ' ';
break;
}
else if (*p == '\n')
lineno++;
*p++ = ' ';
}
continue;
}
if (*p == '/' && *(p+1) == '/') { /* consume EOL comments */
*p++ = ' ', *p++ = ' ';
while (*p != '\n') { *p++ = ' '; }
}
if (*p == '\n') {
lineno++;
if (*bol == '#') {
register char *cp;
*p++ = '\0';
/* punt lines with just # (yacc generated) */
for (cp = bol+1;
*cp && (*cp == ' ' || *cp == '\t'); cp++);
if (*cp) goto done;
}
bol = p+1;
}
}
if (*bol != '#')
bol = NULL;
done:
filep->f_p = p;
filep->f_line = lineno;
return(bol);
}
#ifdef VMS
void unlink (name)
char *name;
{
char command[200];
/* Use the DELETE command (executed through SYSTEM), since VMS does not
support UNLINK */
sprintf (command, "delete %s;", name);
system (command);
}
#endif
#ifdef USG
int rename (from, to)
char *from, *to;
{
(void) unlink (to);
if (link (from, to) == 0) {
unlink (from);
return 0;
} else {
return -1;
}
}
#endif /* USG */
void
redirect(line, makefile)
char *line,
*makefile;
{
struct stat st;
FILE *fdin, *fdout;
char backup[ BUFSIZ ],
buf[ BUFSIZ ];
boolean found = FALSE;
int len;
/*
* if makefile is "-" then let it pour onto stdout.
*/
if (makefile && *makefile == '-' && *(makefile+1) == '\0')
return;
/*
* use a default makefile is not specified.
*/
if (!makefile) {
if (stat("makefile", &st) == 0)
makefile = "makefile";
else if (stat("Makefile", &st) == 0)
makefile = "Makefile";
else
log_fatal("[mM]akefile is not present\n");
}
else
stat(makefile, &st);
if ((fdin = fopen(makefile, "r")) == NULL)
log_fatal("cannot open \"%s\"\n", makefile);
sprintf(backup, "%s.bak", makefile);
unlink(backup);
fclose(fdin);
if (rename(makefile, backup) < 0)
log_fatal("cannot rename %s to %s\n", makefile, backup);
fdin = fopen(backup, "r");
if ((fdout = freopen(makefile, "w", stdout)) == NULL)
log_fatal("cannot open \"%s\"\n", backup);
len = strlen(line);
while (fgets(buf, BUFSIZ, fdin) && !found) {
if (*buf == '#' && strncmp(line, buf, len) == 0)
found = TRUE;
fputs(buf, fdout);
}
if (!found) {
if (verbose)
do_log("Adding new delimiting line \"%s\" and dependencies...\n",
line);
puts(line); /* same as fputs(fdout); but with newline */
}
fflush(fdout);
#ifdef USG
chmod(makefile, st.st_mode);
#else
/* fchmod(fileno(fdout), st.st_mode); */
chmod(makefile, st.st_mode);
#endif /* USG */
}